package com.gepengjun.springboot.jwt.interceptor;

import com.auth0.jwt.JWT;
import com.auth0.jwt.exceptions.JWTDecodeException;
import com.auth0.jwt.exceptions.TokenExpiredException;
import com.gepengjun.springboot.jwt.annotation.RequiredLogin;
import com.gepengjun.springboot.jwt.constant.JwtConstant;
import com.gepengjun.springboot.jwt.entity.Suser;
import com.gepengjun.springboot.jwt.exception.JwtException;
import com.gepengjun.springboot.jwt.service.SuserService;
import com.gepengjun.springboot.jwt.util.JwtUtil;
import com.gepengjun.springboot.jwt.util.RedisUtil;
import org.apache.commons.lang3.StringUtils;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.lang.reflect.Method;

public class AuthenticationInterceptor implements HandlerInterceptor {

    @Resource
    private SuserService suserService;

    @Resource
    private RedisUtil redisUtil;

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        String token = request.getHeader("token");

        if (! (handler instanceof HandlerMethod)){
            return false;
        }

        HandlerMethod handlerMethod = (HandlerMethod)handler;
        Method method = handlerMethod.getMethod();
        RequiredLogin requiredLogin = method.getAnnotation(RequiredLogin.class);
        if (requiredLogin != null && requiredLogin.required()) {
            if (token == null){
                throw new JwtException("无token,请重新登录");
            }
            String userId;
            try {
                userId = JWT.decode(token).getClaim("userId").asString();
            } catch (JWTDecodeException e) {
                throw new JwtException("无效的token,请重新登录");
            }
            Suser suser = suserService.getById(userId);
            if (suser == null) {
                throw new JwtException("用户不存在,请重新登录");
            }
            try {
                JwtUtil.verify(token, suser.getPassword());
                return true;
            } catch (TokenExpiredException e) {
                e.printStackTrace();
                StringBuffer jwtTokenKey = new StringBuffer(JwtConstant.JWT_TOKEN).append(":").append(userId);
                String redisToken = redisUtil.get(jwtTokenKey.toString());
                //redis里未保存token 说明距离上次登录操作 已过7天  需要重新登录
                if (StringUtils.isEmpty(redisToken)){
                    throw new JwtException("token已过期,请重新登录");
                }

                if (token.equals(redisToken)){
                    String newToken = JwtUtil.getToken(suser.getSerialNo(),suser.getUsername(),suser.getPassword());
                    response.setHeader("newToken",newToken);
                    response.setHeader("Access-Control-Expose-Headers","newToken");
                    redisUtil.set(jwtTokenKey.toString(), newToken , redisUtil.getExpireTime(jwtTokenKey.toString()));
                    return true;
                }else {
                    throw new JwtException("token已过期,已经生成新的token");
                }
            } catch (Exception e) {
                throw new JwtException("无效token");
            }
        }else {
            return true;
        }
    }

    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {

    }

    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {

    }
}
